using System;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Web.UI.WebControls;

using AForge.Video;
using AForge.Video.DirectShow;

using Graphene.Processing;
using Graphene.Storing;

namespace Graphene
{
    public partial class MainForm : Form
    {
        public static readonly int VIEWFINDER_WIDTH = 320;
        public static readonly int VIEWFINDER_HEIGHT = 240;
        public static readonly string MOUSELOOK_CHECKBOX_UNCHECKED_TEXT = "Enable Mouselook and keyboard movement.";
        public static readonly string MOUSELOOK_CHECKBOX_CHECKED_TEXT = "Press Esc to disable mouselook and keyboard movement.";
        public static readonly string SELECTION_NONE = "- none -";
        public static readonly string RUNNING_TEXT = "Stop Video Sources";
        public static readonly string STOPPED_TEXT = "Start Video Sources";
        public static readonly Graphene.Storing.PointInt2D VIEWFINDER_SIZE_FOR_MARKER_CALIBRATION = new Storing.PointInt2D(160, 120);
        public static readonly string ACCEPTABLE_TEXT = "Acceptable";
        public static readonly string NOT_ACCEPTABLE_TEXT = "Not Acceptable";

        private Model model;

        public MainForm(Model m)
        {
            this.model = m;

            InitializeComponent();
            MyInitializeComponent();
        
            updatingVideoListsGeneral = false;         
        }

        private void UpdateVideoListsGeneral(            
            GetVideoSourceSelectionDelegate getVideoSourceSelectionPrimary,
            GetVideoSourceSelectionDelegate getVideoSourceSelectionSecondary,
            ComboBox videoListPrimaryCombobox,
            ComboBox videoListSecondaryCombobox,
            System.Windows.Forms.CheckBox startStopCheckbox
            )
        {
            /* To prevent recursion. */
            if (updatingVideoListsGeneral)
            {
                return;
            }
            updatingVideoListsGeneral = true;

            AForge.Video.DirectShow.FilterInfo selection1 = getVideoSourceSelectionPrimary();
            AForge.Video.DirectShow.FilterInfo selection2 = getVideoSourceSelectionSecondary();
            videoListPrimaryCombobox.Items.Clear();
            videoListSecondaryCombobox.Items.Clear();
            videoListPrimaryCombobox.Items.Add(SELECTION_NONE);
            videoListSecondaryCombobox.Items.Add(SELECTION_NONE);

            AForge.Video.DirectShow.FilterInfoCollection filterInfos = model.AvailableVideoDeviceList;
            List<VideoSource> videoSources = new List<VideoSource>(this.model.VideoSources.Values);
            foreach (AForge.Video.DirectShow.FilterInfo filterInfo in filterInfos)
            {
                if (selection2 == null || !selection2.Equals(filterInfo))
                {
                    videoListPrimaryCombobox.Items.Add(filterInfo.Name);
                }
                if (selection1 == null || !selection1.Equals(filterInfo))
                {
                    videoListSecondaryCombobox.Items.Add(filterInfo.Name);
                }
            }
            if (selection1 != null && videoListPrimaryCombobox.Items.Contains(selection1.Name))
            {
                videoListPrimaryCombobox.SelectedItem = selection1.Name;
            }
            else
            {
                videoListPrimaryCombobox.SelectedItem = SELECTION_NONE;
            }
            if (selection2 != null && videoListSecondaryCombobox.Items.Contains(selection2.Name))
            {
                videoListSecondaryCombobox.SelectedItem = selection2.Name;
            }
            else
            {
                videoListSecondaryCombobox.SelectedItem = SELECTION_NONE;
            }

            if (selection1 != null && selection2 != null)
            {
                startStopCheckbox.Enabled = true;
            }
            else
            {
                startStopCheckbox.Enabled = false;
            }

            updatingVideoListsGeneral = false;
        }

        public void UpdateVideoListsFor3DProcessing()
        {
            this.UpdateVideoListsGeneral(                
                this.model.GetVideoSourceSelectionPrimaryFor3DProcessing,
                this.model.GetVideoSourceSelectionSecondaryFor3DProcessing,
                this.videoListPrimaryComboboxFor3DProcessing,
                this.videoListSecondaryComboboxFor3DProcessing,
                this.startStopCheckboxFor3DProcessing
                );
        }

        public void UpdateVideoListsForMarkerCalibration()
        {
            this.UpdateVideoListsGeneral(
                this.model.GetVideoSourceSelectionPrimaryForMarkerCalibration,
                this.model.GetVideoSourceSelectionSecondaryForMarkerCalibration,
                this.videoListComboboxPrimaryForMarkerCalibration,
                this.videoListComboboxSecondaryForMarkerCalibration,
                this.startStopCheckboxForMarkerCalibration
                );
        }

        public void RefreshVideoListButtonForMarkerCalibrationButton_SetClickedHandler(System.EventHandler handler)
        {
            this.refreshVideoListButtonForMarkerCalibration.Click += handler;
        }

        public void VideoListPrimaryComboboxForMarkerCalibration_SetNewSelectionHandler(System.EventHandler handler)
        {
            this.videoListComboboxPrimaryForMarkerCalibration.SelectedValueChanged += handler;
        }
        public void VideoListSecondaryComboboxForMarkerCalibration_SetNewSelectionHandler(System.EventHandler handler)
        {
            this.videoListComboboxSecondaryForMarkerCalibration.SelectedValueChanged += handler;
        }

        public void StartStopCheckboxForMarkerCalibration_SetCheckChangedHandler(System.EventHandler handler)
        {
            this.startStopCheckboxForMarkerCalibration.CheckedChanged += handler;
        }

        public void VideoPictureBoxPrimaryForMarkerCalibration_SetClickedHandler(System.EventHandler handler)
        {
            this.videoPrimaryPictureboxForMarkerCalibration.Click += handler;
        }
        public void VideoPictureBoxSecondaryForMarkerCalibration_SetClickedHandler(System.EventHandler handler)
        {
            this.videoSecondaryPictureboxForMarkerCalibration.Click += handler;            
        }
        public void VideoPictureBoxPrimaryForMarkerCalibration_SetDoubleClickedHandler(System.EventHandler handler)
        {
            this.videoPrimaryPictureboxForMarkerCalibration.DoubleClick += handler;
        }
        public void VideoPictureBoxSecondaryForMarkerCalibration_SetDoubleClickedHandler(System.EventHandler handler)
        {
            this.videoSecondaryPictureboxForMarkerCalibration.DoubleClick += handler;
        }

        public System.Drawing.Point PrimaryVideoPictureBoxForMarkerCalibrationPointToClient(System.Drawing.Point p)
        {
            return this.videoPrimaryPictureboxForMarkerCalibration.PointToClient(p);
        }
        public System.Drawing.Point SecondaryVideoPictureBoxForMarkerCalibrationPointToClient(System.Drawing.Point p)
        {
            return this.videoSecondaryPictureboxForMarkerCalibration.PointToClient(p);
        }

        public void TolerancePrimaryTrackbar_SetValueChangedHandler(System.EventHandler handler)
        {
            this.tolerancePrimaryTrackbar.ValueChanged += handler;
        }
        public void ToleranceSecondaryTrackbar_SetValueChangedHandler(System.EventHandler handler)
        {
            this.toleranceSecondaryTrackbar.ValueChanged += handler;
        }

        public void TolerancePrimaryTrackbar_ClickReleasedHandler(System.Windows.Forms.MouseEventHandler handler)
        {
            //this.TolerancePrimaryTrackbar.KeyUp += handler;
            //this.TolerancePrimaryTrackbar.Leave += handler;
            //this.TolerancePrimaryTrackbar.LostFocus += handler;
            this.TolerancePrimaryTrackbar.MouseUp += handler;                           
        }
        public void ToleranceSecondaryTrackbar_ClickReleasedHandler(System.Windows.Forms.MouseEventHandler handler)
        {
            this.ToleranceSecondaryTrackbar.MouseUp += handler;
        }

        public void AddSampleButtonForMarkerCalibration_SetClickHandler(System.EventHandler handler)
        {
            this.addSampleButtonForMarkerCalibration.Click += handler;
        }

        public void SampleListboxForMarkerCalibration_SetSelectedValueChangedHandler(System.EventHandler handler)
        {
            this.sampleListboxForMarkerCalibration.SelectedValueChanged += handler;
        }

        public void AddNewMarkerForMarkerCalibration_SetClickedHandler(System.EventHandler handler)
        {
            this.addNewMarkerButtonForMarkerCalibration.Click += handler;             
        }

        public void RemoveSampleButtonForMarkerCalibration_SetClickHandler(System.EventHandler handler)
        {
            this.removeSampleButtonForMarkerCalibration.Click += handler;
        }

        public void ClearSamplesButtonForMarkerCalibration_SetClickHandler(System.EventHandler handler)
        {
            this.clearSamplesButtonForMarkerCalibration.Click += handler;
        }

        public void UpdateGridForMarkerCalibration()
        {                        
            Dictionary<MarkerInImage, MarkerInImage> markers = this.model.MarkersFor3D;
            List<MarkerInImage> primarys = new List<MarkerInImage>(markers.Keys);
            List<MarkerInImage> secondarys = new List<MarkerInImage>(markers.Values);

            System.Drawing.Pen blackPen = new System.Drawing.Pen(new System.Drawing.SolidBrush(System.Drawing.Color.Black));

            this.markers3DGrid.Rows.Clear();
            for (int markerIndex = 0; markerIndex < markers.Count; markerIndex++)
            {
                DataGridViewRow row = new DataGridViewRow();

                DataGridViewTextBoxCell primaryNameCell = new DataGridViewTextBoxCell();
                primaryNameCell.Value = primarys[markerIndex].MyName;
                row.Cells.Add(primaryNameCell);

                System.Drawing.Bitmap primaryBitmap = new System.Drawing.Bitmap(15, 15);
                System.Drawing.Graphics primaryGraphics = System.Drawing.Graphics.FromImage(primaryBitmap);
                System.Drawing.Brush primaryBrush = new System.Drawing.SolidBrush(primarys[markerIndex].Color);
                primaryGraphics.FillRectangle(primaryBrush, 0, 0, 14, 14);
                primaryGraphics.DrawRectangle(blackPen, 0, 0, 14, 14);                
                DataGridViewImageCell primaryColorCell = new DataGridViewImageCell(false);
                primaryColorCell.Value = primaryBitmap;
                row.Cells.Add(primaryColorCell);

                DataGridViewTextBoxCell primaryToleranceCell = new DataGridViewTextBoxCell();
                primaryToleranceCell.Value = primarys[markerIndex].SearchShadeTolerance.ToString();
                row.Cells.Add(primaryToleranceCell);

                DataGridViewTextBoxCell secondaryNameCell = new DataGridViewTextBoxCell();
                secondaryNameCell.Value = secondarys[markerIndex].MyName;
                row.Cells.Add(secondaryNameCell);                                              
                
                System.Drawing.Bitmap secondaryBitmap = new System.Drawing.Bitmap(15, 15);
                System.Drawing.Graphics secondaryGraphics = System.Drawing.Graphics.FromImage(secondaryBitmap);
                System.Drawing.Brush secondaryBrush = new System.Drawing.SolidBrush(secondarys[markerIndex].Color);
                secondaryGraphics.FillRectangle(secondaryBrush, 0, 0, 14, 14);
                secondaryGraphics.DrawRectangle(blackPen, 0, 0, 14, 14);                
                DataGridViewImageCell secondaryColorCell = new DataGridViewImageCell(false);
                secondaryColorCell.Value = secondaryBitmap;
                row.Cells.Add(secondaryColorCell);

                DataGridViewTextBoxCell secondaryToleranceCell = new DataGridViewTextBoxCell();
                secondaryToleranceCell.Value = secondarys[markerIndex].SearchShadeTolerance.ToString();
                row.Cells.Add(secondaryToleranceCell); 

                this.markers3DGrid.Rows.Add(row);
            }      
        }

        public void UpdateGridForStereoProcessing()
        {
            Dictionary<MarkerInImage, MarkerInImage> markers = this.model.MarkersFor3D;
            List<MarkerInImage> primarys = new List<MarkerInImage>(markers.Keys);
            List<MarkerInImage> secondarys = new List<MarkerInImage>(markers.Values);

            System.Drawing.Pen blackPen = new System.Drawing.Pen(new System.Drawing.SolidBrush(System.Drawing.Color.Black));

            this.MarkersGridForStereoProcessing.Rows.Clear();
            for (int markerIndex = 0; markerIndex < markers.Count; markerIndex++)
            {
                DataGridViewRow row = new DataGridViewRow();

                DataGridViewCheckBoxCell useCell = new DataGridViewCheckBoxCell(false);
                useCell.Selected = false;
                row.Cells.Add(useCell);

                DataGridViewTextBoxCell primaryNameCell = new DataGridViewTextBoxCell();
                primaryNameCell.Value = primarys[markerIndex].MyName;
                row.Cells.Add(primaryNameCell);

                System.Drawing.Bitmap primaryBitmap = new System.Drawing.Bitmap(15, 15);
                System.Drawing.Graphics primaryGraphics = System.Drawing.Graphics.FromImage(primaryBitmap);
                System.Drawing.Brush primaryBrush = new System.Drawing.SolidBrush(primarys[markerIndex].Color);
                primaryGraphics.FillRectangle(primaryBrush, 0, 0, 14, 14);
                primaryGraphics.DrawRectangle(blackPen, 0, 0, 14, 14);
                DataGridViewImageCell primaryColorCell = new DataGridViewImageCell(false);
                primaryColorCell.Value = primaryBitmap;
                row.Cells.Add(primaryColorCell);

                DataGridViewTextBoxCell primaryToleranceCell = new DataGridViewTextBoxCell();
                primaryToleranceCell.Value = primarys[markerIndex].SearchShadeTolerance.ToString();
                row.Cells.Add(primaryToleranceCell);

                DataGridViewTextBoxCell secondaryNameCell = new DataGridViewTextBoxCell();
                secondaryNameCell.Value = secondarys[markerIndex].MyName;
                row.Cells.Add(secondaryNameCell);

                System.Drawing.Bitmap secondaryBitmap = new System.Drawing.Bitmap(15, 15);
                System.Drawing.Graphics secondaryGraphics = System.Drawing.Graphics.FromImage(secondaryBitmap);
                System.Drawing.Brush secondaryBrush = new System.Drawing.SolidBrush(secondarys[markerIndex].Color);
                secondaryGraphics.FillRectangle(secondaryBrush, 0, 0, 14, 14);
                secondaryGraphics.DrawRectangle(blackPen, 0, 0, 14, 14);
                DataGridViewImageCell secondaryColorCell = new DataGridViewImageCell(false);
                secondaryColorCell.Value = secondaryBitmap;
                row.Cells.Add(secondaryColorCell);

                DataGridViewTextBoxCell secondaryToleranceCell = new DataGridViewTextBoxCell();
                secondaryToleranceCell.Value = secondarys[markerIndex].SearchShadeTolerance.ToString();
                row.Cells.Add(secondaryToleranceCell);

                this.MarkersGridForStereoProcessing.Rows.Add(row);
            }  
        }

        private void MyInitializeComponent()
        {
            this.namePrimaryColumn.Width = 120;
            this.namePrimaryColumn.MinimumWidth = 120;
            this.namePrimaryColumn.Resizable = DataGridViewTriState.False;

            this.colorPrimaryColumn.Width = 30;
            this.colorPrimaryColumn.MinimumWidth = 30;
            this.colorPrimaryColumn.Resizable = DataGridViewTriState.False;

            this.tolerancePrimaryColumn.Width = 50;
            this.tolerancePrimaryColumn.MinimumWidth = 50;
            this.tolerancePrimaryColumn.Resizable = DataGridViewTriState.False;

            this.nameSecondaryColumn.Width = 120;
            this.nameSecondaryColumn.MinimumWidth = 120;
            this.nameSecondaryColumn.Resizable = DataGridViewTriState.False;
            
            this.colorSecondaryColumn.Width = 30;
            this.colorSecondaryColumn.MinimumWidth = 30;
            this.colorSecondaryColumn.Resizable = DataGridViewTriState.False;

            this.toleranceSecondaryColumn.Width = 50;
            this.toleranceSecondaryColumn.MinimumWidth = 50;
            this.toleranceSecondaryColumn.Resizable = DataGridViewTriState.False;
        }

        /* 3D Processing */
        public void RefreshVideoListButtonFor3DProcessing_SetClickedHandler(System.EventHandler handler)
        {
            this.refreshVideoListButtonFor3DProcessing.Click += handler;
        }

        public void VideoListPrimaryComboboxFor3DProcessing_SetNewSelectionHandler(System.EventHandler handler)
        {
            this.videoListPrimaryComboboxFor3DProcessing.SelectedValueChanged += handler;            
        }
        public void VideoListSecondaryComboboxFor3DProcessing_SetNewSelectionHandler(System.EventHandler handler)
        {
            this.videoListSecondaryComboboxFor3DProcessing.SelectedValueChanged += handler;
        }

        public void StartStopCheckboxFor3DProcessing_SetCheckChangedHandler(System.EventHandler handler)
        {
            this.startStopCheckboxFor3DProcessing.CheckedChanged += handler;
        }
        

        /* Only to prevent recursion in UpdateVideoSourcesFor3DDropdowns(). */
        private bool updatingVideoListsForTwinDropdowns;
        private bool updatingVideoListsForMarkerCalibration;        
        private bool updatingVideoListsGeneral;
    }
}